#ifndef STRAIGHTLINE_SLP_H_
#define STRAIGHTLINE_SLP_H_

#include <algorithm>
#include <cassert>
#include <string>
#include <list>
#include <iostream>

namespace A {

class Stm;
class Exp;
class ExpList;
enum BinOp { PLUS = 0, MINUS, TIMES, DIV };
// some data structures used by interp
class Table;
class IntAndTable;

/*----------------------------------------------------------------------------------*/
//语句
class Stm {
 public:
  virtual int MaxArgs() const = 0;
  virtual Table *Interp(Table *) const = 0;
};

//复合语句
class CompoundStm : public Stm {
 public:
  CompoundStm(Stm *stm1, Stm *stm2) : stm1(stm1), stm2(stm2) {}
  int MaxArgs() const override;//参考slp.cc中的实现
  Table *Interp(Table *) const override;//参考slp.cc中的实现

 private://成员们
  Stm *stm1, *stm2;
};

//赋值语句
class AssignStm : public Stm {
 public:
  AssignStm(std::string id, Exp *exp) : id(std::move(id)), exp(exp) {}
  int MaxArgs() const override;//参考slp.cc中的实现
  Table *Interp(Table *) const override;//参考slp.cc中的实现

 private://成员们
  std::string id;
  Exp *exp;
};

//打印语句
class PrintStm : public Stm {
 public:
  explicit PrintStm(ExpList *exps) : exps(exps) {}
  int MaxArgs() const override;//参考slp.cc中的实现
  Table *Interp(Table *) const override;//参考slp.cc中的实现

 private://成员们
  ExpList *exps;
};
/*----------------------------------------------------------------------------------*/
//表达式
class Exp {
  public:
    // TODO: you'll have to add some definitions here (lab1).
    // Hints: You may add interfaces like `int MaxArgs()`,
    //        and ` IntAndTable *Interp(Table *)`
    virtual int MaxArgs() const = 0;
    virtual IntAndTable* InterpExp(Table *t) const = 0;

};

//标识符表达式
class IdExp : public Exp {
 public:
  explicit IdExp(std::string id) : id(std::move(id)) {}
  // TODO: you'll have to add some definitions here (lab1).
  int MaxArgs() const override;//参考slp.cc中的实现
  IntAndTable* InterpExp(Table *t) const override;//参考slp.cc中的实现

 private://成员们
  std::string id;
};

//数字表达式
class NumExp : public Exp {
 public:
  explicit NumExp(int num) : num(num) {}
  // TODO: you'll have to add some definitions here.
  int MaxArgs() const override;//参考slp.cc中的实现
  IntAndTable* InterpExp(Table *t) const override;//参考slp.cc中的实现
  
 private://成员们
  int num;
};

//操作符表达式
class OpExp : public Exp {
 public:
    OpExp(Exp *left, BinOp oper, Exp *right)
        : left(left), oper(oper), right(right) {}
    // TODO: you'll have to add some definitions here.
    int MaxArgs() const override;//参考slp.cc中的实现
    IntAndTable* InterpExp(Table *t) const override;//参考slp.cc中的实现

 private://成员们
    Exp *left;
    BinOp oper;
    Exp *right;
};

//序列表达式((语句，表达式)称为序列表达式)
class EseqExp : public Exp {
  public:
    EseqExp(Stm *stm, Exp *exp) : stm(stm), exp(exp) {}
    // TODO: you'll have to add some definitions here.
    int MaxArgs() const override;//参考slp.cc中的实现
    IntAndTable* InterpExp(Table *t) const override;//参考slp.cc中的实现

  private://成员们
    Stm *stm;
    Exp *exp;
};
/*----------------------------------------------------------------------------------*/
//表达式列表
class ExpList {
 public:
  // TODO: you'll have to add some definitions here (lab1).
  // Hints: You may add interfaces like `int MaxArgs()`, `int NumExps()`,
  //        and ` IntAndTable *Interp(Table *)`
  virtual int MaxArgs() const = 0;
  virtual int NumExps() const = 0;
  virtual IntAndTable* Interp(Table *) const = 0;
  virtual void IntegrityExpList(std::list<Exp*>&) const = 0;
};

//对偶表达式列表
class PairExpList : public ExpList {
 public:
  PairExpList(Exp *exp, ExpList *tail) : exp(exp), tail(tail) {}
  // TODO: you'll have to add some definitions here (lab1).
  int MaxArgs() const override;
  int NumExps() const override;
  IntAndTable* Interp(Table *) const override;
  void IntegrityExpList(std::list<Exp*>&) const override;

 private://成员们
  Exp *exp;
  ExpList *tail;
};

//终止表达式列表
class LastExpList : public ExpList {
 public:
  LastExpList(Exp *exp) : exp(exp) {}
  // TODO: you'll have to add some definitions here (lab1).
  int MaxArgs() const override;
  int NumExps() const override;
  IntAndTable* Interp(Table *) const override;
  void IntegrityExpList(std::list<Exp*>&) const override;
  
 private://成员们
  Exp *exp;
};
/*----------------------------------------------------------------------------------*/
//表
class Table {
 public:
  Table(std::string id, int value, const Table *tail)
      : id(std::move(id)), value(value), tail(tail) {}
  int Lookup(const std::string &key) const;
  Table *Update(const std::string &key, int val) const;

 private:
  std::string id;
  int value;
  const Table *tail;
};

//整数 + 表 结构体
struct IntAndTable {
  int i;
  Table *t;
  IntAndTable(int i, Table *t) : i(i), t(t) {}
};

}  // end of namespace A

#endif  // STRAIGHTLINE_SLP_H_
